import { applyDecorators, Type } from '@nestjs/common';
import {
  ApiExtraModels,
  ApiOkResponse,
  getSchemaPath,
  ApiBody,
} from '@nestjs/swagger';
import { ResponseDto } from '../dto/response.dto';
import { PageDto } from '../dto/page.dto';
import { QueryPageDto } from '../dto/query.page.dto';

export const ApiObjOkResponse = <T extends Type<unknown>>(dataDto: T) =>
  applyDecorators(
    ApiExtraModels(ResponseDto, dataDto ?? ResponseDto),
    ApiOkResponse({
      schema: {
        allOf: [
          { $ref: getSchemaPath(ResponseDto) },
          {
            properties: {
              data: { $ref: getSchemaPath(dataDto) },
            },
          },
        ],
      },
    }),
  );

export const ApiQueryPage = <T extends Type<unknown>>(dataDto: T) =>
  applyDecorators(
    ApiExtraModels(QueryPageDto, dataDto),
    ApiBody({
      schema: {
        allOf: [
          { $ref: getSchemaPath(QueryPageDto) },
          {
            properties: {
              model: { $ref: getSchemaPath(dataDto) },
            },
          },
        ],
      },
    }),
  );

export const ApiPageOkResponse = <T extends Type<unknown>>(dataDto: T) =>
  applyDecorators(
    ApiExtraModels(ResponseDto, PageDto, dataDto),
    ApiOkResponse({
      schema: {
        allOf: [
          { $ref: getSchemaPath(ResponseDto) },
          {
            properties: {
              data: {
                $ref: getSchemaPath(PageDto),
                properties: {
                  record: {
                    type: 'array',
                    items: { $ref: getSchemaPath(dataDto) },
                  },
                },
              },
            },
          },
        ],
      },
    }),
  );

export const ApiArrayOkResponse = <T extends Type<unknown>>(dataDto: T) =>
  applyDecorators(
    ApiExtraModels(ResponseDto, dataDto),
    ApiOkResponse({
      schema: {
        allOf: [
          { $ref: getSchemaPath(ResponseDto) },
          {
            properties: {
              data: {
                type: 'array',
                $ref: getSchemaPath(dataDto),
              },
            },
          },
        ],
      },
    }),
  );
